מבוא למדעי המחשב ולולאות הרצאה 3 :משפטים,תנאים מבוסס על השקפים שנערכו ע"י שי ארצי, גיתית רוקנשטיין, איתן אביאור, סאהר אסמיר,מיכאל אלעד, רון קימל ודן רביב. עדכון אחרון: סמסטר חורף 2012.
תוכנייה משפטים בשפת משפטי תנאי (Statements) C - לולאות for while דוגמאות: מציאת GCD מציאת שורש מציאת מספר ראשוני (אלגוריתם אוקלידס) (שיטת ניוטון-רפסון) 2
Statements - משפטים בשפת C משפטביטוי statement) :(expression ביטוי שאחריו';' נחשבכמשפט. לעיתיםקיימות תוצאותלוואילמשפט כזה ולעיתיםלא. y++; x = ; משפטריק statement) :(empty מורכב מ- ';' בלבד. איןלמשפט תוצאותלוואי. משפט מורכב :(compound statement) רצף משפטיםהמוקפיםבסוגריים מסולסלים {} { כזה נקרא גםבלוק. רצף נחשב כמשפט אחד. } t = x; x = y; y = t; 3
תוכנייה משפטים בשפת משפטי תנאי (Statements) C - לולאות for while דוגמאות: מציאת GCD (אלגוריתם אוקלידס) מציאת שורש (שיטת ניוטון-רפסון) 4
משפט if expression 0 Statement 0 if (expression) statement הינו,True זהו משפט מהצורה: אם ערך האמת של expression מבצעיםאת.statement אם ערך האמת של expression הינו,False מדלגיםעלביצוע statement (ועוברים למשפט הבא אחריו). לרוב, statement יהיה משפט מורכב. לדוגמה: if(b*b < 4*a*c) { printf( no real solution to the quad. equation.\n ); return 1; } 5
משפט if-else expression 0 0 if (expression) statement1 else statement2 זהו משפט מהצורה: st1 st2 אם ערך האמת של expression הינו,True מבצעיםאת statement1 מדלגיםעל statement2 ועוברים למשפט הבא. אם ערך האמת של expression הינו,False מדלגיםעל,statement1 מבצעיםאת statement2 ואזממשיכים לבא. if(tomorrow_is_rainy == y ) printf( Take your umbrella.\n"); else printf( Leave the umbrella at home.\n"); לדוגמה: 6
קינון if-else מה מבצע המשפט הבא? if(a==1) if(b==2) if(b==2) printf("***"); printf("***"); else else printf("###"); printf("###"); b =2 2 a =1 *** ### 1 ### ### if(a==1) { if(b==2) printf("***"); } else printf("###"); ה- else מקושר תמיד ל- if האחרון. ניתן להפריד ביניהם באמצעות{...}. 7
תוכנייה משפטים בשפת משפטי תנאי (Statements) C - לולאות for while דוגמאות: מציאת GCD מציאת שורש מציאת מספר ראשוני (אלגוריתם אוקלידס) (שיטת ניוטון-רפסון) 8
לולאות קטע קודהמתבצע מספרפעמיםנקרא לולאה.(loop) מספרהפעמים תלויבערכו שלביטויהמחושב במהלך ריצתהתכנית. כל אחדמביצועי הלולאהנקרא איטרציה.(iteration) ב- C קיימים שלושה משפטיםהמאפשרים ביצוע לולאות: while statement for statement do-while statement 9
לולאת while expression 0 while (expression) statement זהו משפט מהצורה: 0 statement כל עודערך האמת שלexpression.statement מבצעיםאת,True הינו לדוגמה, חישוב עצרת: unsigned int n, factorial = 1, i = 2; scanf( %d, &n); while(i <= n) { factorial *= i++; } printf("n!= %d", factorial); 10
לולאת do-while statement do statement while(expression); זהו משפט מהצורה: 0 expression 0 מבצעיםאת statement כלעוד ערך האמת של expression הינו True (פעם אחתלפחות). לדוגמה, קליטת מספר חיובי: int x; do { printf("please enter a positive number: "); scanf("%d", &x); } while (x <= 0); 11
לולאת for expression1 זהו משפט מהצורה: for(expression1;expression2;expression3) statement expression2 0 statement 0 מבצעיםאת expression1 (אתחול) ואזכלעוד ערך האמת של expression2 (תנאי) הינו,True מבצעיםאת statement ואז expression3 (קידום). כ"א משלושת הביטוייםיכוללהיותריק. expression3 expression1 while (expression2) { statement expression3 } שקול ל: 12
- המשך לולאת for sum = 0; for(i = 1; i <= n; i++) sum += i * i; : n i= 1 i 2 חישוב הביטוי for(i = 2 ; i <= n; i++) factorial *= i; חישוב עצרת: printf("n!= %d", factorial); i = 2; while(i <= n) { factorial *= i; i++; } printf("n!= %d", factorial); השווה מול השימוש ב- while : 13
דוגמה: מציאת המספר הקטן ביותר בקלט scanf("%d", &min); for(i = 1; i < n; i++) { scanf("%d", &num); if(num < min) min = num; } #include<limits.h>... min = INT_MAX; for(i = 0; i < n; i++) { scanf("%d", &num); if(num < min) min = num; } נכתוב תוכניתהמקבלת כקלט סדרה שלn מספרים (שלמים) ומוצאת עבורם אתהערך המינימאלי. אלגנטי? קריאתהערכים נעשיתפעם מחוץ ללולאה, ובהמשך בתוכה. ואם נרצה את כל הקריאות בלולאה? נאתחלאתmin ל- INT_MAX קבוע המוגדר ב- limits.h וערכו הואהערך השלם הגדול ביותר שיכולמשתנה מטיפוסint לקבל. זה אינו הפתרון היחיד האפשרי! 14
- המשך לולאת for שימוש באופרטור פסיק,: חישובביטוי מהצורה exp1, exp2 מתבצע ע"יחישוב exp1 חישוב.exp2 ערכו (טיפוסו) שלביטוי זההינו ערכו (טיפוסו) של.exp2 ולאחריו sum = 0; for(i = 1; i <= n; i++) sum += i * i; קודם ראינו את התוכנית דרך נוספת לביצוע הסכום הנ"ל: for(sum = 0, i = 1; i <= n; sum += i * i, i++); ככלל, בסוגרייםהצמודים ל- for יופיעוביטוייםהקשורים בבקרת הלולאה (אך לא בתכנה), ולכןנעדיףאת הפתרון הראשון שראינו. 15
משפטי break ו- continue משפטיםמיוחדים לצורך שבירתרצף הביצוע בקוד. break כאשר מופיע בתוך switch גורם לסיוםה- switch ומעבר למשפט הבא. כאשר מופיע בתוך לולאה, גורם לסיוםהלולאה ומעבר למשפט הבא. continue ניתןלשימושבלולאותבלבד. בלולאה. גורם למעבר לסוף האיטרציה הנוכחית 16
דוגמה לשימוש ב- continue for(i = 0; i < 100; i++) { scanf("%d",&num); if(num < 0) continue; sum += num; } i = 0; while(i < 100) { scanf("%d",&num); if(num < 0) continue; sum += num; i++; } קטע קוד זה מבצע קריאה של 100 מספרים שלמים וסוכם את אי-השליליים שביניהם. מה ההבדל בין הקוד העליון לקוד הבא? האם הם שקולים? בקוד זה נידרש לספק 100 מספרים אי-שליליים על מנת לסיים התוכנית. מה נדרש לשנות על מנת לקבל שקילות לתוכנית העליונה? 17
דוגמה לשימוש ב- break sum = 0; while(1) { scanf("%d",&num); if(num < 0) break; sum += num; } קטע קודזה מסכם אתהמספריםבקלטעד הראשון. (לא כולל) המספר השלילי 18
לולאות אינסופיות לולאות בהן ערך הביטוי הנבדק שונה מ- 0 תמיד. לולאות אינסופיותנגרמותלעיתיםבשל שגיאהובמקרים אלו ניתןלצאת מהן עלידי עצירתהתכניתבאמצעותמערכת ההפעלה (אוכיבוי המחשב). while(1) { } for( ;1; ) { } ניתן לייצר לולאות אינסופיות במכוון. לדוגמה: for( ; ; ) { } היציאה מלולאות אינסופיות מכוונות נעשית באמצעות פקודות כגון.return, break 19
דיוק בבדיקת תנאי הלולאה האם שתי הלולאות הבאות מבצעות את אותה הפעולה? for(x = 0.0; x < 3.0; x += 0.2) for(x = 0.0; x!= 3.0; x += 0.2) ככלל, נעדיף אופרטוריםשלסדר >) <, <=, (>=, שלהשוואה (=!,==) בתנאיהביצוע שללולאות. על פני אופרטורים 20
תוכנייה משפטים בשפת משפטי תנאי (Statements) C - לולאות for while דוגמאות: מציאת GCD מציאת שורש מציאת מספר ראשוני (אלגוריתם אוקלידס) (שיטת ניוטון-רפסון) 4 הרצאה מבוא למדעי המחשב. כל הזכויות שמורות 21
מציאת המכנה המשותף הגדול ביותר (GCD).(Greatest Common Divider) מחלק משותף גדול ביותר :GCD בהינתןשנישלמיםחיוביים m ו- n gcd(m,n) הוא השלםהגדולביותר שמחלקאת שניהם. פתרון ביה"ס יסודי: פרק את שני המספרים לגורמים ראשוניים. מכפלת הגורמים הראשוניים המשותפים היא ה- GCD. לדוגמא: n=270 m=700 n = 2 * 3 3 * 5 m = 2 2 * 5 2 * 7 gcd(700, 270) = 2 * 5 = 10 4 הרצאה מבוא למדעי המחשב. כל הזכויות שמורות 22
פירוק מספר לגורמים ראשוניים המשפט היסודי (אקסיומה) של האריתמטיקהקובע כי כל מספר שלםיכול להיכתב בצורהייחודית כמכפלת מספרים ראשוניים. פירוק מספרn לגורמים: אםn ראשוני, הוסף אתn לקבוצתהמחלקיםועצור. אחרת, עבור סדרתית עלהמספרים הראשונייםעד שורש n. הוסף אתp, המספר הראשוני הראשון המחלק את n, לקבוצתהמחלקיםוחזור על התהליך עם.n/p לדוגמה, עבור :n=30 5 = 5 * 5 3 = 15 * 15 2 = 30 קושי: האלגוריתםאינומעשי עבור n גדול. למשלעבור מספר בן 18 ספרות יש צורך לעבור עלכל הראשוניים עד 1,000,000,000 (השורש שלו!). מסיבה זו, פירוק לגורמיםראשוניים משמש בסיס לקריפטוגרפיה מודרנית. 4 הרצאה מבוא למדעי המחשב. כל הזכויות שמורות 23
אלגוריתם אויקלידס לחישוב GCD אלגוריתם אוקלידס מתבסס על הטענות המתמטיות הבאות: r. = m % ואתn מחלקאתn ורק אםq אם ואתn מחלקאתm q נובע מהשוויון.m = r + q * n עבורn השונה מ- 0 gcd(n,m%n).gcd(m,n) = m gcd(m, 0) = עבורm שאינו 0. מה קורה אםm n? > Euclid Aristotle Eudoxus of Cnidus 4 הרצאה מבוא למדעי המחשב. כל הזכויות שמורות 24
ההיגיון הבסיסי נניחכיq הוא מחלקכלשהו המחלקבאופן שלםהן אתm והן אתn. נניחכיm>n. m-2n m-n m q n ברור כי.gcd(m,n)=gcd(m-n,n) באופן דומה,,gcd(m,n)=gcd(m-2n,n) וכו'. אם נמשיך בהפחתה נגיע לקשר:.gcd(m,n)=gcd(n,m%n) היפוך הסדר נובע מכך שבהכרח:.m%n<n 4 הרצאה מבוא למדעי המחשב. כל הזכויות שמורות 25
אלגוריתם אויקלידס, דוגמאות דוגמא 1 דוגמא 2 m = q*n + r m n m n 700 = 2*270 + 160 270 = 1*160 + 110 160 = 1*110 + 50 110 = 2*50 + 10 50 = 5*10 + 0 700 270 270 160 160 110 110 50 50 10 10 0 100 17 17 15 15 2 2 1 1 0 4 הרצאה מבוא למדעי המחשב. כל הזכויות שמורות 26
אלגוריתם אויקלידס, הוכחת נכונות נסמןב- m i ו- n i אתערכי המשתניםm ו- n בתוםהאיטרציה ה- i. שמורה (תכונה שנשמרתבמהלך האלגוריתם): gcd(m 0,n 0 ) = gcd(m i,n i ) הוכחת השמורה נעשיתבאינדוקציה על i: בסיס: מיידי. הנחה: ) i gcd(m 0,n 0 ) = gcd(m i,n צעד האינדוקציה: הנחת האינדוקציה טענה מתמטית אלגוריתם gcd(m i+1,n i+1 ) = gcd(n i,m i %n i ) = gcd(m i,n i ) = gcd(m 0,n 0 ) בתום האיטרציה האחרונה: gcd(m 0,n 0 ) = gcd(m N,n N ) = gcd(m N,0) = m N 4 הרצאה מבוא למדעי המחשב. כל הזכויות שמורות 27
אלגוריתם אויקלידס, קידוד #include <stdio.h> RUN int main() { unsigned int m, n; } scanf("%u%u", &n, &m); while(n!= 0) { unsigned int temp = n; n = m % n; m = temp; } if(m!= 0) printf("the gcd is %d\n", m); return 0; 4 הרצאה מבוא למדעי המחשב. כל הזכויות שמורות 28
דוגמה: מציאת שורשי משוואה הגדרת הבעיה: חשב אתנקודת החיתוךשלפונקציה נתונה f(x) עם ה- 0, כלומרפתור,f(x)=0 עבורx ממשי. f(x) x ניישם שיטה איטרטיבית לחיפוש הפתרון שיטת ניוטון-רפסון. נתחיל בנקודה x 0 וממנה נעדכן לנקודות המתקרבות לחציית ציר ה- x. 29
עקרון הפעולה f x f x f x נזכיר פיתוח לטור טיילור סביב נקודה: 2 ( + δ ) = ( ) + '( ) δ + δ +... f(x) לפונקציות חלקות ו- מספיק קטן, נקבל כי f ( x f ''( x) 2 δ + δ ) = 0 δ = f ( x) f '( x) x+δ x x 30
מציאת שורשים בשיטת ניוטון-רפסון שיטת ניוטון-רפסון (Newton-Raphson) - שיטה למציאתשורששל פונקציה גזירה בתחוםנתוןע"י קיזוז הסטייה שלה. נתוניעזר נדרשים: נקודה הנגזרתשל הפונקציה. קרובה לשורש, ושיטה יעילה לחישוב x 0 x 0 31
שיטת ניוטון-רפסון - המשך השיטה: חזור: עבור לנקודה שבה חותך המשיק (הנגזרת) את הצירהאופקי x i+1 = x i - f(x i ) / f'(x i ) הנחה: הקטע איננומכיל נקודותקיצון (שבהן הנגזרת מתאפסת) f(x 0 ) f(x 0 ) / (x 0 - x 1 ) = tan α = f'(x 0 ) x 1 x 0 32
שיטת ניוטון-רפסון - הדגמה x 1 x 0 x 3 x 2 33
- תנאי עצירה שיטת ניוטון-רפסון x i+1 - x i < δ f(x i+1 ) < ε בפתרון שנראה, נשתמשבמספר האיטרציותכתנאי עצירה. שילוב התנאיםל- δו- ε נשאיר כתרגיל. < ε x i+1 x i < δ 34
קוד מקור עבור הפונקציה 9 - f(x)=x 2 #include <stdio.h> #define MAX_ITERATIONS 10 int main() { double a, fa, fda; int i; בעיה: נדרשלכתוב תוכנית חדשה לכל פונקציה f. פתרון: שימוש בפונקציות ומצביעים לפונקציות (בהמשך). RUN } scanf("%lf", &a); fa = a*a - 9; for(i = 0; i < MAX_ITERATIONS && (fa!= 0); ++i) { fa = a*a - 9; fda = 2*a; /* what if fda == 0? */ a = a - fa/fda; printf("iteration: %d, Solution: %.12f\n", i, a); } printf("solution is: %.12f\n", a); return 0; 35
אלגוריתם לבדיקת ראשוניות בהינתן שלםחיובי n, ישלקבועהאם הוא ראשוני. מחלקבתחום 2,3,,n-1. איננוראשוניאםורקאםיש ל- n n unsigned int is_prime = 1, n, i; RUN... if(n == 1) is_prime = 0; else { for(i = 2; i < n; i++) if(n % i == 0) is_prime = 0; } if(is_prime) printf("%d is a prime\n", n); else printf("%d is not a prime\n", n); 36
#include <math.h>... int is_prime = 1, n, i;... if(n == 1 (n!= 2 && n % 2 == 0)) is_prime = 0; else { int sqrt_n = (int)sqrt(n); for(i = 3; i <= sqrt_n; i+=2) if(n % i == 0){ is_prime = 0; break;} } if(is_prime) printf("%d is a prime\n", n); else printf("%d is not a prime\n", n);... בדיקת ראשוניות: הצעות ייעול RUN אםn איננו 2 אך מתחלק ב- 2 אזי הוא אינו ראשוני. מספיק לבדוק מחלקים אפשריים עד שורשn. כיוון ש- n אינו זוגי, ניתן לדלגעל בדיקת המחלקים הזוגיים. כשנמצא מחלק שלם, אין סיבה להמשיך בבדיקה. 37